package lumis.portal.webfilereplication;

import java.util.List;

import lumis.portal.PortalException;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.event.AbstractPortalEventObserver;
import lumis.portal.event.IPortalEvent;
import lumis.portal.event.IPortalEventFilter;
import lumis.portal.event.PortalEventFilters;
import lumis.portal.event.PortalEventOperationType;
import lumis.portal.filesystem.PortalBaseFolder;
import lumis.portal.filesystem.PortalFile;
import lumis.portal.filesystem.PortalFilePath;
import lumis.portal.filesystem.event.ClusterFileSystemAddEvent;
import lumis.portal.filesystem.event.ClusterFileSystemDeleteEvent;
import lumis.portal.filesystem.event.ClusterFileSystemUpdateEvent;
import lumis.portal.filesystem.event.FileSystemEvent;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.portal.user.UserConfig;
import lumis.util.ITransaction;
import lumis.util.log.ILogger;
import lumis.util.log.LoggerFactory;

/**
 * Observer that replicates files and directories.
 * 
 * @version $Revision: 13093 $ $Date: 2011-05-28 18:40:18 -0300 (Sat, 28 May 2011) $
 * @since 6.0.0
 */
public class WebFileReplicationObserver extends AbstractPortalEventObserver
{
	private static ILogger logger = LoggerFactory.getLogger(WebFileReplicationObserver.class);

	@Override
	public IPortalEventFilter getEventFilter()
	{
		return PortalEventFilters.byInstanceOf(ClusterFileSystemAddEvent.class,
				ClusterFileSystemUpdateEvent.class, ClusterFileSystemDeleteEvent.class);
	}

	@SuppressWarnings("unchecked")
	public void onEvent(IPortalEvent ev) throws PortalException
	{
		FileSystemEvent event = (FileSystemEvent) ev;
		
		// check if the file belongs to WWW
		PortalFile file = event.getFile();
		PortalFilePath portalFilePath = file.getPortalFilePath();
		if (portalFilePath.getBaseFolder() != PortalBaseFolder.WWW)
			return;

		// read persistedReplications
		List<WebFileReplication> persistedReplications;
		ITransaction transaction = PortalTransactionFactory.createTransaction();
		try
		{
			transaction.begin();

			persistedReplications = ManagerFactory.getEntityManager().createNamedQuery(
					WebFileReplication.NAMED_QUERY_FIND_WEB_FILE_REPLICATION)
					.setHint("org.hibernate.readOnly", Boolean.TRUE)
					.getResultList();

			transaction.commit();
		}
		finally
		{
			transaction.dispose();
		}
		
		// do the replications
		SessionConfig sessionConfig = null;
		try
		{
			sessionConfig = ManagerFactory.getAuthenticationManager().impersonate(UserConfig.USER_SYSTEM_ID);
			PortalEventOperationType operationType = event.getOperationType();
			for (WebFileReplication replication : persistedReplications)
			{
				try
				{
					if (operationType == PortalEventOperationType.DELETE)
					{
						replication.replicateDeletion(file);
					}
					else
					{
						replication.replicateWrite(file);
					}
				}
				catch (Exception e)
				{
					logger.error("Could not replicate operation '" + operationType + "' on file '" + file + "' for replication '" + replication.getName() + "'", e);
				}
			}
		}		
		finally
		{
			if (sessionConfig != null)
			{
				ManagerFactory.getAuthenticationManager().endImpersonation(sessionConfig);	
			}
		}
	}
}